Continuing on from my last post in this how to series on Items this post is going to look at how you can go about creating, deleting, moving, copying,exporting different Items and we will also look at the important batch operations which help when you need to perform actions on multiple Items at the same time.
As I have mentioned previously in this series when your dealing with Exchange Objects your dealing with Rich data-types that vary greatly eg If you compare the properties on an Email object with that of a Task while they share a set of common properties what makes a Task a Task is its unique properties such as Percent complete, Start Time etc which have all been dutifully documented in this Exchange Protocol document. As this is the first I've mentioned this I would strongly recommend you check out the Open Specification Development Center which is a really brilliant resource for any reference information you need about using Exchange data types or EWS in general.
Creating Items
With EWS when you create Items you use the Strongly Typed class for that particular Item you want to create for example Email, Appointment, Tasks etc. The exception for this is when you have an object Type where this in no Strong Type such as Notes (or StickyNotes), Journals Items etc for these you use the MessageType class and then change the ItemClass property to the IPM. type you want. Lets look at a few examples the first sample shows you how to Send an Email and the Second how to create an Appointment.
Creating an Appointment
Okay now lets look at what to do when you need to create an Item where there isn't a Strong Type. The first thing you need to know is all the underlying Extended Mapi properties that make this Item work the most accurate source for this is the Exchange protocol documents for example for a Note this would
this. The other way is to look at an example Item with a Mapi Editor like OutlookSpy or MFCMapi (personally i use both) where you can see all the underlying extended properties there's a good sample of doing this here. Here's a sample for creating a StickyNote
Creating Items in Public Folders or custom Mailbox folders
To create these type of objects in Public folders there is no real difference to a normal mailbox folder other then in the save method eg $snStickyNote.Save() you need to use the EWSid of the public folder in question see Part two in the how to series for information on how to get the EWSid of the folder.
Copy and Moving Items between folders
With EWS you have the ability to move Items between folders in a mailbox or copy them between folders or between different Mailboxes the later can be useful if your looking to replicate one folder to the other. With the Managed API there is a simple Copy or Move Method on an Item that takes the EWS FolderID of the folder where you want to copy\move the Item to. For a simple sample lets look at a script that the finds a Message based on its subject then demonstrates first ly copy and then a move to a folder called destination folder located in the Inbox
This type of script works okay when you only need to copy or move one item at a time however when you want to move multiple items its better to use the Batch methods which essentially batch the individual move or copy requests into one request. This can be useful when you are doing archiving, cleanup or deletion type scripts. The following sample will create a folder under the Inbox called January2011 and then query for all the items in the Inbox from January2011 using a AQS string it will then do a batch move of these items to the January2011 folder.
Deleting Items
Deleting Items works the same as Copy or Move with the addition of passing the delete mode you wish for example to delete the Item instead of copying/Moving it you would use something like
Exporting and Importing Items
One frequently asked question about EWS is how can i export to a PST or MSG file and unfortunately the answer is you can't these are Office file formats so if you want to use them you need to use an Office API like the OOM or my recommendation would be to use Redemption/RDO http://www.dimastr.com/redemption/home.htm. (Or you can use the Exchange Management Shell and the export-... cmdlets).
However there are a few methods you can use to Export and Import Items in other formats one format you can use for Email Messages is to use the Mime content of a message which is essentially the RFC822 stream of the message (or more or less the stream you would see submitted to and from the MTA over SMTP). Using the Mime Content is only good for Email messages and it wont include any custom Mapi properties or message flags so it would not be a full fidelity export of a message. Here's a sample of how to export the last message received to an EML file.
To Import an EML file you essentially upload the MIME content you either saved from the export script or other EML file from another email client. To make sure the message doesn't appear as a draft you need to set the SentFlag on the message. For example to upload an EML file
The other way you can export and Import Items with EWS on Exchange 2010 is to use the new ExportItems and UploadItems operations. These operations export items in a Opaque data stream that contains all the Store properties of the underlying Item which make its a full fidelity copy of that underlying Item. There is nothing in the Managed API to allow you to use these operations so you need to use either WSDL proxy code or raw SOAP for more information have a look at these two links
http://msdn.microsoft.com/en-us/library/hh135142%28v=exchg.140%29.aspx
and
http://gsexdev.blogspot.com.au/2011/02/exporting-and-uploading-mailbox-items.html
That's it for this post in the next post I'll look at the special operations in EWS to Get the OOFStatus, FreeBusy and create Inbox Rules.
As I have mentioned previously in this series when your dealing with Exchange Objects your dealing with Rich data-types that vary greatly eg If you compare the properties on an Email object with that of a Task while they share a set of common properties what makes a Task a Task is its unique properties such as Percent complete, Start Time etc which have all been dutifully documented in this Exchange Protocol document. As this is the first I've mentioned this I would strongly recommend you check out the Open Specification Development Center which is a really brilliant resource for any reference information you need about using Exchange data types or EWS in general.
Creating Items
With EWS when you create Items you use the Strongly Typed class for that particular Item you want to create for example Email, Appointment, Tasks etc. The exception for this is when you have an object Type where this in no Strong Type such as Notes (or StickyNotes), Journals Items etc for these you use the MessageType class and then change the ItemClass property to the IPM. type you want. Lets look at a few examples the first sample shows you how to Send an Email and the Second how to create an Appointment.
- # Create Email Object
- $EmailMessage = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage -ArgumentList $service
- #Set the Subject
- $EmailMessage.Subject = "Subject of Email blah"
- #Set the Body of Messsage
- $EmailMessage.Body = "Message Body Blah blah"
- #Add Recipients
- $EmailMessage.ToRecipients.Add("targetemail@domain.com")
- #Send Message SendandSave will save the Message to the Sender Sent Item Folder
- $EmailMessage.SendAndSaveCopy()
- ##Create a Calendar Appointment
- $Appointment = New-Object Microsoft.Exchange.WebServices.Data.Appointment -ArgumentList $service
- #Set Start Time
- $Appointment.Start = [system.DateTime]::Now.AddDays(7)
- #Set End Time
- $Appointment.End = [system.DateTime]::Now.AddDays(7).AddHours(1)
- #Set Subject
- $Appointment.Subject = "Drink Coffee with Friend"
- #Set the Location
- $Appointment.Location = "Good Coffee Shop"
- #Set any Notes
- $Appointment.Body = "Dont forget to mention X and Y"
- #Create Appointment will save to the default Calendar
- $Appointment.Save()
- #Create Sticky Note
- #First we use the EmailMessage Class (MessageType) this ensures we can change the ItemClass
- $snStickyNote = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage -ArgumentList $service
- #Set the Subject of the Note
- $snStickyNote.Subject = "Stick Note Subject"
- #Change the ItemClass to IPM.StickNote
- $snStickyNote.ItemClass = "IPM.StickyNote"
- #Set the Text body of the Note
- $snStickyNote.Body = "First Line `r`nNext Line"
- #Start Note specific Extended properties
- #Define the Guid for the Notes Named properties
- $noteGuid = new-object Guid("0006200E-0000-0000-C000-000000000046")
- #Set the Colour of the Note
- $snColour = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition($noteGuid,35584, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer)
- #Set the Height of the Note
- $snHeight = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition($noteGuid,35586, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer)
- #Set the Width of the Note
- $snWidth = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition($noteGuid,35587, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer)
- #Postion from Left
- $snLeft = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition($noteGuid,35588, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer)
- #Postion from Top
- $snTop = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition($noteGuid,35589, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer)
- #Set Note props
- $snStickyNote.SetExtendedProperty($snColour,3)
- $snStickyNote.SetExtendedProperty($snHeight,200)
- $snStickyNote.SetExtendedProperty($snWidth,166)
- $snStickyNote.SetExtendedProperty($snLeft,80)
- $snStickyNote.SetExtendedProperty($snTop,80)
- #Save the Item to the Notes Folder
- $snStickyNote.Save([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Notes)
To create these type of objects in Public folders there is no real difference to a normal mailbox folder other then in the save method eg $snStickyNote.Save() you need to use the EWSid of the public folder in question see Part two in the how to series for information on how to get the EWSid of the folder.
Copy and Moving Items between folders
With EWS you have the ability to move Items between folders in a mailbox or copy them between folders or between different Mailboxes the later can be useful if your looking to replicate one folder to the other. With the Managed API there is a simple Copy or Move Method on an Item that takes the EWS FolderID of the folder where you want to copy\move the Item to. For a simple sample lets look at a script that the finds a Message based on its subject then demonstrates first ly copy and then a move to a folder called destination folder located in the Inbox
- #Move and Copy sample
- #AQSString
- $AqsString = "Subject:=`"Test Mail Move`""
- #Bind to Inbox
- $folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
- $Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
- #Get the ID of the folder to move to
- $fvFolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1000)
- $fvFolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Shallow;
- $SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,"MoveDestination")
- $findFolderResults = $Inbox.FindFolders($SfSearchFilter,$fvFolderView)
- #Define ItemView to retrive just 1000 Items
- $ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
- $fiItems = $null
- do{
- $fiItems = $service.FindItems($Inbox.Id,$AqsString,$ivItemView)
- #[Void]$service.LoadPropertiesForItems($fiItems,$psPropset)
- foreach($Item in $fiItems.Items){
- # Copy the Message
- $Item.Copy($findFolderResults.Folders[0].Id)
- # Move the Message
- $Item.Move($findFolderResults.Folders[0].Id)
- }
- $ivItemView.Offset += $fiItems.Items.Count
- }while($fiItems.MoreAvailable -eq $true)
- #Batch Move Sample
- #AQSString
- $Range = "01/01/2012..01/30/2012"
- $AQSString = "System.Message.DateReceived:" + $Range
- #Bind to Inbox
- $folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
- $Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
- #Create the folder to move to
- $NewFolder = new-object Microsoft.Exchange.WebServices.Data.Folder($service)
- $NewFolder.DisplayName = "January2011"
- $NewFolder.Save($Inbox.Id)
- #Define ItemView to retrive just 1000 Items
- $ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
- $fiItems = $null
- do{
- #Create the collection of ItemIds to perform batch request
- $Itemids = [activator]::createinstance(([type]'System.Collections.Generic.List`1').makegenerictype([Microsoft.Exchange.WebServices.Data.ItemId]))
- $fiItems = $service.FindItems($Inbox.Id,$AQSString,$ivItemView)
- #[Void]$service.LoadPropertiesForItems($fiItems,$psPropset)
- foreach($Item in $fiItems.Items){
- "Processing : " + $Item.Subject
- $Itemids.add($Item.Id)
- }
- $Result = $service.MoveItems($Itemids,$NewFolder.Id)
- [INT]$Rcount = 0
- foreach ($res in $Result){
- if ($res.Result -eq [Microsoft.Exchange.WebServices.Data.ServiceResult]::Success){
- $Rcount++
- }
- }
- $Rcount.ToString() + " Items moved successfully"
- $ivItemView.Offset += $fiItems.Items.Count
- }while($fiItems.MoreAvailable -eq $true)
Deleting Items works the same as Copy or Move with the addition of passing the delete mode you wish for example to delete the Item instead of copying/Moving it you would use something like
- $Item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::SoftDelete)
Exporting and Importing Items
One frequently asked question about EWS is how can i export to a PST or MSG file and unfortunately the answer is you can't these are Office file formats so if you want to use them you need to use an Office API like the OOM or my recommendation would be to use Redemption/RDO http://www.dimastr.com/redemption/home.htm. (Or you can use the Exchange Management Shell and the export-... cmdlets).
However there are a few methods you can use to Export and Import Items in other formats one format you can use for Email Messages is to use the Mime content of a message which is essentially the RFC822 stream of the message (or more or less the stream you would see submitted to and from the MTA over SMTP). Using the Mime Content is only good for Email messages and it wont include any custom Mapi properties or message flags so it would not be a full fidelity export of a message. Here's a sample of how to export the last message received to an EML file.
- #Eml Export sample
- #Define PropertySet
- $psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.ItemSchema]::MimeContent)
- #Bind to the Inbox
- $folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
- $Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
- #Set the ItemView to only return 1 Email
- $ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1)
- #Define PropertySet to load MimeContent
- $psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.ItemSchema]::MimeContent)
- $fiItems = $service.FindItems($folderid,$ivItemView)
- foreach($itItem in $fiItems.Items){
- $itItem.load($psPropset)
- $fileName = "C:\temp\exportedmail.eml"
- $fiFile = new-object System.IO.FileStream($fileName, [System.IO.FileMode]::Create)
- $fiFile.Write($itItem.MimeContent.Content, 0,$itItem.MimeContent.Content.Length)
- $fiFile.Close()
- }
- #Upload Eml Sample
- $folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
- $Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
- #Crete Email Object
- $emUploadEmail = new-object Microsoft.Exchange.WebServices.Data.EmailMessage($service)
- #Read File
- [byte[]]$bdBinaryData1 = get-content -encoding byte "C:\temp\exportedmail.eml"
- #Set Mime Content in Message
- $emUploadEmail.MimeContent = new-object Microsoft.Exchange.WebServices.Data.MimeContent("us-ascii", $bdBinaryData1);
- #Set Sent Message Flags which means message wont appear as a Draft
- $PR_Flags = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(3591, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);
- $emUploadEmail.SetExtendedProperty($PR_Flags,"1")
- $emUploadEmail.Save($Inbox.Id)
http://msdn.microsoft.com/en-us/library/hh135142%28v=exchg.140%29.aspx
and
http://gsexdev.blogspot.com.au/2011/02/exporting-and-uploading-mailbox-items.html
That's it for this post in the next post I'll look at the special operations in EWS to Get the OOFStatus, FreeBusy and create Inbox Rules.